Clone Method Example (VC++)

This example uses the Clone method to create copies of a Recordset and then lets the user position the record pointer of each copy independently.

#import "C:\Program Files\Common Files\System\ADO\msado15.dll" \
    no_namespace rename("EOF", "EndOfFile")
#define TESTHR(x) if FAILED(x) _com_issue_error(hr)

#include <stdio.h>
#include <ole2.h>
#include <conio.h>

// Function Declarations.
void CloneX(void);
void PrintProviderError(_ConnectionPtr pConnection);
void PrintComError(_com_error &e);

///////////////////////////////////////////////////////////
//                                                       //
//      Main Function                                    //
//                                                       //
///////////////////////////////////////////////////////////
void main()
{
    if(FAILED(::CoInitialize(NULL)))
        return;

    CloneX();

    ::CoUninitialize();
}

///////////////////////////////////////////////////////////
//                                                       //
//      CloneX Function                                  //
//                                                       //
///////////////////////////////////////////////////////////

void  CloneX()
{
    // Define ADO object pointers.
    // Initialize pointers on define.
    // These are in the ADODB::  namespace.

    _RecordsetPtr  arstStores[3];

    //Define Other Variables
    HRESULT hr = S_OK;
    int intLoop = 0;
    _bstr_t strSQL;
    _bstr_t strMessage;
    _bstr_t strFind;
    int intLoop1 = 0;
    char *tempStr;
    bool boolFlag = TRUE;
    char m_szS_stor_name[150];

    // Assign SQL statement and connection string to variables.
    strSQL = "SELECT stor_name FROM Stores ORDER BY stor_name";

    _bstr_t strCnn("Provider=sqloledb;Data Source=srv;"
            "Initial Catalog=Pubs;User Id=sa;Password=;");

    try 
    {
        // Open recordset as a static cursor type recordset.
        arstStores[0].CreateInstance(__uuidof(Recordset));
        arstStores[0]->CursorType = adOpenStatic;
        arstStores[0]->LockType = adLockBatchOptimistic;

        TESTHR(arstStores[0]->Open(strSQL,strCnn, adOpenStatic,
            adLockBatchOptimistic,adCmdText));

        // Create two clones of the original Recordset.
        arstStores[1] = arstStores[0]->Clone(adLockBatchOptimistic);
        arstStores[2] = arstStores[0]->Clone(adLockBatchOptimistic);

        while (boolFlag)
        {
            // Loop through the array so that on each pass,
            // the user is searching a different copy of the
            // same Recordset.
            for (intLoop = 1; intLoop <= 3 ; intLoop++)
            {
                // Ask for search string while showing where
                // the current record pointer is for each Recordset.
                printf("Recordsets from stores table:\n");

                _bstr_t str1 = arstStores[0]->Fields->
                    GetItem("stor_name")->Value;
                printf("\t1 - Original - Record pointer at %s",
                    (LPCSTR)str1);

                _bstr_t str2 = arstStores[1]->Fields->
                    GetItem("stor_name")->Value;
                printf("\n\t2 - Clone - Record pointer at %s", 
                    (LPCSTR)str2);

                _bstr_t str3 = arstStores[2]->Fields->
                    GetItem("stor_name")->Value;
                printf("\n\t3 - Clone - Record pointer at %s",
                    (LPCSTR)str3); 

                printf("\n\nEnter search string for # %d\n"
                    ô, or press Enter to quit.ö, intLoop);
                gets(m_szS_stor_name);

                // Trim the string.
                tempStr = strtok(m_szS_stor_name, "  \t");
                strMessage = tempStr;
                if (tempStr == NULL)
                {
                    boolFlag = FALSE;
                    break;
                }

                // Find the search string; if there's no
                // match, jump to the last record.
                intLoop1 = intLoop -1;

                arstStores[intLoop1]->Filter = "stor_name >= '" + 
                    strMessage + "'";

                if (arstStores[intLoop1]->EndOfFile)
                {
                    arstStores[intLoop1]->Filter = (long)adFilterNone;
                    arstStores[intLoop1]->MoveLast();
                }
            }
        } // End of While Loop

        // Clean up objects before exit.
        arstStores[0]->Close();
        arstStores[1]->Close();
        arstStores[2]->Close();
    }

    catch(_com_error &e)
    {
        // Notify the user of errors if any.
        _variant_t vtConnect = arstStores[0]->GetActiveConnection();

        switch(vtConnect.vt)
        {
            case VT_BSTR:
                PrintComError(e);
                break;
            case VT_DISPATCH:
                PrintProviderError(vtConnect);
                break;
            default:
                printf("Errors occured.");
                break;
        }
    }
};

///////////////////////////////////////////////////////////
//                                                       //
//      PrintProviderError Function                      //
//                                                       //
///////////////////////////////////////////////////////////

void PrintProviderError(_ConnectionPtr pConnection)
{
    // Print Provider Errors from Connection object.
    // pErr is a record object in the Connection's Error collection.
    ErrorPtr pErr = NULL;
    long     nCount = 0;
    long     i = 0;

    if( (pConnection->Errors->Count) > 0)
    {
        nCount = pConnection->Errors->Count;
        // Collection ranges from 0 to nCount -1.
        for(i = 0; i < nCount; i++)
        {
            pErr = pConnection->Errors->GetItem(i);
            printf("\t Error number: %x\t%s", pErr->Number,
                (LPCSTR) pErr->Description);
        }
    }
}

///////////////////////////////////////////////////////////
//                                                       //
//      PrintComError Function                           //
//                                                       //
///////////////////////////////////////////////////////////

void PrintComError(_com_error &e)
{
    _bstr_t bstrSource(e.Source());
    _bstr_t bstrDescription(e.Description());

    // Print Com errors.  
    printf("Error\n");
    printf("\tCode = %08lx\n", e.Error());
    printf("\tCode meaning = %s", e.ErrorMessage());
    printf("\tSource = %s\n", (LPCSTR) bstrSource);
    printf("\tDescription = %s\n", (LPCSTR) bstrDescription);
}

CloneX.h:

#include "icrsint.h"

// This Class extracts only store name 
// from "stores" table.
class CStores : public CADORecordBinding
{
BEGIN_ADO_BINDING(CStores)

    //Column stor_name is the 1st field in the recordset  

    ADO_VARIABLE_LENGTH_ENTRY2(1, adVarChar, m_szS_stor_name, 
         sizeof(m_szS_stor_name), lS_stor_nameStatus, FALSE)

END_ADO_BINDING()

public:
    CHAR    m_szS_stor_name[150];
    ULONG   lS_stor_nameStatus;
};